package com.fqgj.sentry.policy.engine.resolver;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fqgj.sentry.policy.engine.domain.Condition;
import com.fqgj.sentry.policy.engine.domain.ConditionGroup;
import com.fqgj.sentry.policy.engine.domain.ConditionGroupResult;
import com.fqgj.sentry.policy.engine.domain.Decision;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionGroupComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionGroupTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.PolicyTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.RuleComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.RuleTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.VariableTypeEnum;
import com.fqgj.sentry.policy.engine.domain.Policy;
import com.fqgj.sentry.policy.engine.domain.PolicyResult;
import com.fqgj.sentry.policy.engine.domain.PolicySet;
import com.fqgj.sentry.policy.engine.domain.Rule;
import com.fqgj.sentry.policy.engine.domain.RuleResult;
import com.fqgj.sentry.policy.engine.domain.ScoreCalculator;
import com.fqgj.sentry.policy.engine.domain.Variable;
import com.fqgj.sentry.policy.engine.domain.VariableMap;
import com.fqgj.sentry.policy.engine.domain.VariableOrConstant;
import com.fqgj.sentry.policy.engine.domain.Weight;
import com.fqgj.sentry.policy.engine.domain.WeightRange;
import com.fqgj.sentry.policy.engine.utils.Utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * Created by kennykong on 2017/7/15.
 */

public class CheckFormat {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        ObjectMapper configure = mapper.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);

        String json = null;
        PolicySet p = buildPolicySet();
        try {
            json = mapper.writeValueAsString(p);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        System.out.println(json);
        String path = Utils.getPath() + "policies/policySetGen.json";
        System.out.println(path);
        try {
            File f = new File(URI.create(path));
            if (f.exists()) {
                f.createNewFile();
            }
            FileWriter fw = new FileWriter(f, false);
            fw.write(json);
            fw.flush();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            PolicySet p1 = mapper.readValue(json, PolicySet.class);
            System.out.println(p1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static PolicySet buildPolicySet() {
        PolicySet ps = new PolicySet();
        ps.setEventId(1L);
        ps.setInputVarMap(genVarMap());
        ps.setPolicySetId(123456L);
        ps.setInputVarMap(genVarMap());
        List<Policy> psl = new ArrayList();
        psl.add(buildPolicy());
        ps.setPolicySet(psl);
        return ps;
    }

    public static Policy buildPolicy() {
        Policy policy = new Policy();
        policy.setPolicyId(12345L);
        policy.setPolicyType(PolicyTypeEnum.DECIDE);
        policy.setRuleCompose(RuleComposeEnum.WEIGHT);
        policy.setRuleList(buildRuleList());
        policy.setPolicyResult(generatePolicyResult());
        policy.setInitalScoreVariable(genVar());
        try {
            policy.setWeightRange(genWeightRange());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return policy;
    }

    public static PolicyResult generatePolicyResult() {
        PolicyResult pr = new PolicyResult();
        pr.setSumWeightScore(100d);
        pr.setPolicyDecision(genDecision());
        pr.setSumScore(1000d);
        pr.setHit(true);
        return pr;
    }

    public static Rule buildRule() {
        Rule r = new Rule();
        r.setConditionGroupCompose(ConditionGroupComposeEnum.ALL);
        r.setHitDecisionOption(genDecision());
        r.setRuleType(RuleTypeEnum.CUSTOM);
        r.setWeight(buildWeight());
        r.setRuleResult(generateRuleResult());

        List<ConditionGroup> cgl = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            ConditionGroup cg = buildConditionGroup();
            cgl.add(cg);
        }
        r.setConditionGroups(cgl);
        r.setRuleId(1234L);
        r.setRuleName("rule_abc");
        return r;
    }

    public static List<Rule> buildRuleList() {
        List l = new ArrayList();
        for (int i = 0; i < 3; i++) {
            Rule r = buildRule();
            l.add(r);
        }
        return l;
    }

    public static RuleResult generateRuleResult() {
        RuleResult rr = new RuleResult();
        rr.setHit(true);
        rr.setDecision(genDecision());
        rr.setWeightScore(5d);
        return rr;
    }

    public static ConditionGroup buildConditionGroup() {
        ConditionGroup cg = new ConditionGroup();
        cg.setConditionGroupType(ConditionGroupTypeEnum.GROUP);
        cg.setConditionCompose(ConditionComposeEnum.AND);
        List<Condition> cl = new ArrayList();
        for (int i = 0; i < 3; i++) {
            Condition c = buildCondition();
            cl.add(c);
        }
        cg.setConditions(cl);
        cg.setConditionGroupResult(generateConditionGroupResult());
        cg.setScoreCalculator(buildScoreCalculator());
        return cg;
    }

    public static ConditionGroupResult generateConditionGroupResult() {
        ConditionGroupResult cgr = new ConditionGroupResult();
        cgr.setHit(true);
        cgr.setHitScore(0d);
        return cgr;
    }

    public static Condition buildCondition() {
        Condition c = new Condition();
        c.setOperation(">=");
        c.setHit(true);
        c.setFirstVariable(genVar());
        Integer[] para = new Integer[]{1, 2, 3};
        List<Object> params = Arrays.asList(para);
        VariableOrConstant voc = new VariableOrConstant();
        voc.setIsVar(true);
        c.setSecondVariable(voc);
        return c;
    }

    public static Weight buildWeight() {
        Weight w = new Weight();
        Integer[] para = new Integer[]{1, 2};
        List<Object> params = Arrays.asList(para);
        w.setParams(params);
        w.setVariable(genVar());
        w.setWeightExpression("weightScore");

        return w;
    }

    public static ScoreCalculator buildScoreCalculator() {
        ScoreCalculator sc = new ScoreCalculator();
        Integer[] para = new Integer[]{1, 2};
        List<Object> params = Arrays.asList(para);
        sc.setParams(params);
        VariableOrConstant voc = new VariableOrConstant();
        voc.setIsVar(true);
        voc.setVariable(genVar());
        sc.setVariable(voc);
        sc.setExpression("calculateScore");
        return sc;
    }

    public static Variable genVar() {
        Variable var = new Variable();
        var.setId(1234L);
        var.setName("var_key_process");
        var.setValue("var_value");
        var.setVarType(VariableTypeEnum.DOUBLE);
        return var;
    }

    public static VariableMap genVarMap() {
        VariableMap varMap = new VariableMap();
        for (int i = 0; i < 3; i++) {
            String key = "var_" + i;
            Variable var = genVar();
            var.setName(key);
            varMap.setVariable(key, var);
        }
        return varMap;
    }

    public static Decision genDecision() {
        Decision d = new Decision();
        d.setDecisionId(123);
        d.setDecisionName("REJECT");
        d.setPriority(0);
        return d;
    }

    public static List<WeightRange> genWeightRange() {
        List<WeightRange> ranges = new ArrayList<>();
        {
            WeightRange wr = new WeightRange();
            wr.setStart(0d);
            wr.setEnd(20d);
            wr.setDecision(genDecision());
            ranges.add(wr);
        }
        {
            WeightRange wr = new WeightRange();
            wr.setStart(20d);
            wr.setEnd(60d);
            wr.setDecision(genDecision());
            ranges.add(wr);
        }
        {
            WeightRange wr = new WeightRange();
            wr.setStart(60d);
            wr.setEnd(100d);
            wr.setDecision(genDecision());
            ranges.add(wr);
        }
        return ranges;
    }

}

